package br.com.hibernate;

import br.com.config.shard.ShardSelectionStrategyImpl;
import br.com.model.entidade.Pessoa;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.shards.ShardId;
import org.hibernate.shards.ShardedConfiguration;
import org.hibernate.shards.cfg.ConfigurationToShardConfigurationAdapter;
import org.hibernate.shards.cfg.ShardConfiguration;
import org.hibernate.shards.strategy.ShardStrategy;
import org.hibernate.shards.strategy.ShardStrategyFactory;
import org.hibernate.shards.strategy.ShardStrategyImpl;
import org.hibernate.shards.strategy.access.SequentialShardAccessStrategy;
import org.hibernate.shards.strategy.access.ShardAccessStrategy;
import org.hibernate.shards.strategy.resolution.AllShardsShardResolutionStrategy;
import org.hibernate.shards.strategy.resolution.ShardResolutionStrategy;
import org.hibernate.shards.strategy.selection.ShardSelectionStrategy;

public class HibernateUtil {

    private static final SessionFactory sessionFactory = buildSessionFactory();

    private static SessionFactory buildSessionFactory() {
        AnnotationConfiguration config = new AnnotationConfiguration().configure("config/hibernate0.cfg.xml");
        config.addAnnotatedClass(Pessoa.class);

        List shardConfigs = new ArrayList();
        shardConfigs.add(buildShardConfig("config/hibernate0.cfg.xml"));
        shardConfigs.add(buildShardConfig("config/hibernate1.cfg.xml"));

        ShardStrategyFactory shardStrategyFactory = buildShardStrategyFactory();
        ShardedConfiguration shardedConfig = new ShardedConfiguration(
                config,
                shardConfigs,
                shardStrategyFactory);

        return shardedConfig.buildShardedSessionFactory();
    }

    public static SessionFactory getSessionfactory() {
        return sessionFactory;
    }

    private static ShardConfiguration buildShardConfig(String configFile) {
        AnnotationConfiguration prototypeConfig = new AnnotationConfiguration().configure(configFile);
        return new ConfigurationToShardConfigurationAdapter(prototypeConfig);
    }

    private static ShardStrategyFactory buildShardStrategyFactory() {
        return new ShardStrategyFactory() {
            @Override
            public ShardStrategy newShardStrategy(List<ShardId> shardIds) {
                ShardSelectionStrategy pss = new ShardSelectionStrategyImpl();
                ShardResolutionStrategy prs = new AllShardsShardResolutionStrategy(shardIds);
                ShardAccessStrategy pas = new SequentialShardAccessStrategy();
                return new ShardStrategyImpl(pss, prs, pas);
            }
        };
    }
}
